{# 2016-12-25 replace linebreak or more than one | to html <p> tag #}
{% macro paragraph(content="") %}
  {% if content | trim != "" -%}
    <p>{{ content | replace(r/[\n\r]+|(\|{2,})/g,"</p><p>") | safe }}</p>
  {%- endif %}
{% endmacro %}

{% macro warning(content) -%}
  {{ callout(paragraph(content),"warning") | safe }}  
{%- endmacro %}

{% macro warningWrap() -%}
  {{ callout(paragraph(caller()),"warning") | safe }}  
{%- endmacro %}

{% macro alert(content) -%}
  {{ callout(paragraph(content),"danger") | safe }}  
{%- endmacro %}

{% macro alertWrap() -%}
  {{ callout(paragraph(caller()),"danger") | safe }}  
{%- endmacro %}

{% macro alertInline(content) -%}
  {{ htmlTag("span", {class:"callout-danger", style:"background-color: transparent;"}, content) | safe }}  
{%- endmacro %}

{% macro note(content) -%}
  {{ callout(paragraph(content),"info") | safe }}  
{%- endmacro %}

{% macro noteWrap() -%}
  {{ callout(paragraph(caller()),"info") | safe }}  
{%- endmacro %}

{% macro callout(content, type) %}
  {% if content | trim != "" -%}
    <div class="callout callout-{{type}}">{{ content | replace(r/<p>\s*<\/p>/gi,"") | safe }}</div>
  {%- endif %}
{% endmacro %}

{% macro nowrap(content, tag="code", attrs={class: "text-nowrap"}) -%}
  {% if content | trim != "" -%}
    {{ htmlTag(tag, attrs, content) | safe }}
  {%- endif %}
{%- endmacro %}

{% macro mustache(name, tag="code", attrs={"ng-non-bindable": null}, showEvenIfUndefined=false) -%}
  {%- if tag | trim != "" -%}
    {{ htmlTag(tag, attrs, "{{" + jsMustache(name, showEvenIfUndefined) + "}}") }}
  {%- else -%}
    {% raw %}{{{% endraw %}{{jsMustache(name, showEvenIfUndefined)}}{% raw %}}}{% endraw %}
  {%- endif %}
{%- endmacro %}

{% macro jsMustache(name, showEvenIfUndefined) -%}
  {%- if showEvenIfUndefined == true -%}
    {{jsMustache_prefix}}mustache('{{name}}'){{jsMustache_suffix}}
  {%- else -%}
    {{name}}
  {%- endif -%}
{%- endmacro %}

{% macro htmlTag(name="", attrs="", slot="") -%}
  {% if name | trim != "" -%}
    <{{name}}{{ objectStringify(attrs) }}>{{ slot | safe }}</{{name}}>
  {%- else -%}
    {{ slot | safe }}
  {%- endif %}
{%- endmacro %}

{% macro objectStringify(obj) -%}
  {%- if obj != '' -%}
    {%- for key, value in obj -%}
       {%- if value == null %} {{key}}{% else %} {{key}}="{{value}}"{% endif -%}
    {%- endfor -%}
  {%- endif %}
{%- endmacro %}

{% macro bubbleWrap(fullWidth=false) -%}
  {# short message: <samp ng-non-bindable class="bubble"></samp> #}
  {% set styles = null %}
  {% if fullWidth %}
    {% set styles = "width: 99%;" %}
  {% endif %}
  {{ htmlTag("samp", {"ng-non-bindable": null,class: "bubble", style: styles }, caller()) }}
{%- endmacro %}

{% macro bubble(content) -%}
  {# short message: <samp ng-non-bindable class="bubble"></samp> #}
  {{ htmlTag("samp", {"ng-non-bindable": null,class: "bubble"}, content) }}
{%- endmacro %}

{% macro trimWhiteSpace(s) -%}
  {# remove line breaks, blanks, tab #}
  {{ s | replace(r/^(\s)+|(\1)+$/gim,"") | safe }} 
{%- endmacro %}

{% macro namedAnchor(content, anchor) -%}
  {{ content | safe }}{{ htmlTag("a", {
      'name': anchor,
      'id': anchor,
      'escape-hash': true
     }, "") 
  }}
{%- endmacro %}


{% macro defaultLang(lang) %}
<div class="code-default-lang" data-lang="lang-{{lang}}" data-auto-switch="true"></div>
{% endmacro %}

{% macro className(name) %}
<code class="code-api-name">{{ name }}</code>
{% endmacro %}

{% macro spec(name) %}
className-{{ name }}
{% endmacro %}

{% macro langSpecStart(lang) %}
<p class="lang-spec-{{lang}}-start"></p>
{% endmacro %}

{% macro langSpecEnd(lang) %}
<p class="lang-spec-{{lang}}-end"></p>
{% endmacro %}

{% macro titleNote(title,content) %}
  {% if content | trim != "" -%}
  <blockquote><strong> {{title}} </strong><p> {{ content | replace(r/<p>\s*<\/p>/gi,"") | safe }} </p></blockquote>
  {%- endif %}
{% endmacro %}

{% macro relatedLinks(title,links) %}
<div>
  <h2>{{ title }}</h2>
  {{ linksPanel(links) }}
</div>
{% endmacro %}

{% macro linksPanel(links) %}
  <ul class="list-unstyled">
    {% for link in links %}
    <li><a href="{{ link.href }}">{{ link.title }}</a></li>
    {% endfor %}
  </ul>
{% endmacro %}

{% macro useLangSpec(apiOrClassNameKey,langMap) %}
  <div class="code-key" data-code-key="{{apiOrClassNameKey}}"
    {% for kv in langMap %}
      data-{{kv.lang}} = "{{kv.value}}"
    {% endfor %}
  ></div>
{% endmacro %}


{% macro useStorageLangSpec() %}
  {{ useLangSpec('AVObject',[
    { lang: "js", value: "AV.Object" },
    { lang: "objc", value: "AVObject" },
    { lang: "java", value: "AVObject"},
    { lang: "cs", value: "AVObject"},
    { lang: "php", value: "LCObject"},
    { lang: "python", value: "LeanCloud.Object"}
  ])}}
{% endmacro %}
{% macro useIMLangSpec() %}
  {{ useLangSpec('Conversation.id',[
    { lang: "js", value: "Conversation.id" },
    { lang: "objc", value: "AVIMConversation.conversationId" },
    { lang: "java", value: "AVIMConversation.conversationId"},
    { lang: "cs", value: "AVIMConversation.conversationId"}
  ])}}
  {{ useLangSpec('IMClient',[
    { lang: "js", value: "IMClient" },
    { lang: "objc", value: "AVIMClient" },
    { lang: "java", value: "AVIMClient"},
    { lang: "cs", value: "AVIMClient"}
  ])}}
  {{ useLangSpec('Conversation',[
    { lang: "js", value: "Conversation" },
    { lang: "objc", value: "AVIMConversation" },
    { lang: "java", value: "AVIMConversation"},
    { lang: "cs", value: "AVIMConversation"}
  ])}}
  {{ useLangSpec('conversation.send',[
    { lang: "js", value: "conversation.send" },
    { lang: "objc", value: "[conversation sendMessage]" },
    { lang: "java", value: "conversation.sendMessage"},
    { lang: "cs", value: "conversation.SendAsync"}
  ])}}
  {{ useLangSpec('INVITED',[
    { lang: "js", value: "INVITED" },
    { lang: "objc", value: "AVIMClientDelegate.invitedByClientId" },
    { lang: "java", value: "AVIMConversationEventHandler.onInvited"},
    { lang: "cs", value: "AVIMClient.OnInvited"}
  ])}}
  {{ useLangSpec('KICKED',[
    { lang: "js", value: "KICKED" },
    { lang: "objc", value: "AVIMClientDelegate.kickedByClientId" },
    { lang: "java", value: "AVIMConversationEventHandler.onKicked"},
    { lang: "cs", value: "AVIMClient.OnKicked"}
  ])}}
  {{ useLangSpec('MESSAGE_RECALL',[
    { lang: "js", value: "MESSAGE_RECALL" },
    { lang: "objc", value: "conversation:messageHasBeenUpdated:" },
    { lang: "java", value: "AVIMConversationEventHandler.onMessageRecalled"},
    { lang: "cs", value: "AVIMClient.OnMessageRecalled"}
  ])}}
  {{ useLangSpec('MESSAGE_UPDATE',[
    { lang: "js", value: "MESSAGE_UPDATE" },
    { lang: "objc", value: "conversation:messageHasBeenUpdated:" },
    { lang: "java", value: "AVIMConversationEventHandler.onMessageUpdated"},
    { lang: "cs", value: "AVIMClient.OnMessageModified"}
  ])}}
  {{ useLangSpec('MESSAGE',[
    { lang: "js", value: "MESSAGE" },
    { lang: "objc", value: "AVIMClientDelegate.didReceiveTypedMessage" },
    { lang: "java", value: "AVIMMessageHandler.onMessage"},
    { lang: "cs", value: "AVIMClient.OnMessageReceived"}
  ])}}
  {{ useLangSpec('MEMBERS_JOINED',[
    { lang: "js", value: "MEMBERS_JOINED" },
    { lang: "objc", value: "AVIMClientDelegate.membersAdded" },
    { lang: "java", value: "AVIMMessageHandler.onMemberJoined"},
    { lang: "cs", value: "AVIMClient.OnMembersJoined"}
  ])}}
  {{ useLangSpec('MEMBERS_LEFT',[
    { lang: "js", value: "MEMBERS_LEFT" },
    { lang: "objc", value: "AVIMClientDelegate.membersRemoved" },
    { lang: "java", value: "AVIMMessageHandler.onMemberLeft"},
    { lang: "cs", value: "AVIMClient.OnMembersLeft"}
  ])}}
  {{ useLangSpec('ChatRoom',[
    { lang: "js", value: "ChatRoom" },
    { lang: "objc", value: "AVIMChatRoom" },
    { lang: "java", value: "AVIMChatRoom"},
    { lang: "cs", value: "AVIMChatRoom"}
  ])}}
  {{ useLangSpec('ServiceConversation',[
    { lang: "js", value: "ServiceConversation" },
    { lang: "objc", value: "AVIMServiceConversation" },
    { lang: "java", value: "AVIMServiceConversation"},
    { lang: "cs", value: "AVIMServiceConversation"}
  ])}}
  {{ useLangSpec('TemporaryConversation',[
    { lang: "js", value: "TemporaryConversation" },
    { lang: "objc", value: "AVIMTemporaryConversation" },
    { lang: "java", value: "AVIMTemporaryConversation"},
    { lang: "cs", value: "AVIMTemporaryConversation"}
  ])}}
  {{ useLangSpec('TextMessage',[
    { lang: "js", value: "TextMessage" },
    { lang: "objc", value: "AVIMTextMessage" },
    { lang: "java", value: "AVIMTextMessage"},
    { lang: "cs", value: "AVIMTextMessage"}
  ])}}
  {{ useLangSpec('ImageMessage',[
    { lang: "js", value: "ImageMessage" },
    { lang: "objc", value: "AVIMImageMessage" },
    { lang: "java", value: "AVIMImageMessage"},
    { lang: "cs", value: "AVIMImageMessage"}
  ])}}
  {{ useLangSpec('AudioMessage',[
    { lang: "js", value: "AudioMessage" },
    { lang: "objc", value: "AVIMAudioMessage" },
    { lang: "java", value: "AVIMAudioMessage"},
    { lang: "cs", value: "AVIMAudioMessage"}
  ])}}
  {{ useLangSpec('VideoMessage',[
    { lang: "js", value: "VideoMessage" },
    { lang: "objc", value: "AVIMVideoMessage" },
    { lang: "java", value: "AVIMVideoMessage"},
    { lang: "cs", value: "AVIMVideoMessage"}
  ])}}
  {{ useLangSpec('FileMessage',[
    { lang: "js", value: "FileMessage" },
    { lang: "objc", value: "AVIMFileMessage" },
    { lang: "java", value: "AVIMFileMessage"},
    { lang: "cs", value: "AVIMFileMessage"}
  ])}}
  {{ useLangSpec('LocationMessage',[
    { lang: "js", value: "LocationMessage" },
    { lang: "objc", value: "AVIMLocationMessage" },
    { lang: "java", value: "AVIMLocationMessage"},
    { lang: "cs", value: "AVIMLocationMessage"}
  ])}}
{% endmacro %}
